package com.neo.controllor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.ExcessiveAttemptsException;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.LockedAccountException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.util.SavedRequest;
import org.apache.shiro.web.util.WebUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import com.neo.captcha.DreamCaptcha;
import com.neo.entity.Response;
import com.neo.exception.ExceptionStackTrace;

@Controller
public class HomeController {

	private Logger logger = LoggerFactory.getLogger(HomeController.class);
	
	@Autowired
	private DreamCaptcha dreamCaptcha;
	
	@RequestMapping(value = "/home" )
	public String home(HttpServletRequest request) {
		logger.info(" -------- home ---------");
		return "home";
	}
	
	@RequestMapping(value = "/index")
	public String home() {
		return "index";
	}
	
	@GetMapping({ "/", "/login" })
	public String login() {
		logger.info("================get mapping login=======================");
		return "login";
	}
	//@RequestParam(value="username") String username, @RequestParam(value="password") String password
	
	@ResponseBody
	@PostMapping(value = "/login", produces="application/json;charset=UTF-8")
	public Response login(@RequestBody UsernamePasswordToken usernamePasswordToken, HttpServletRequest request) throws Exception {
		
		logger.info("==>{}", usernamePasswordToken);
		if (StringUtils.isEmpty(usernamePasswordToken.getUsername())) {
			return Response.fail().addData("loginfail", "账户不能为空");
		}
		if (StringUtils.isEmpty(usernamePasswordToken.getPassword())) {
			return Response.fail().addData("loginfail", "密码不能为空");
		}

		String loginFailInfo = null;
		// 把用户名和密码封装为 UsernamePasswordToken 对象
		// rememberme
		usernamePasswordToken.setRememberMe(true);
		Subject currentUser = SecurityUtils.getSubject();
		try {
			// 在调用了login方法后,SecurityManager会收到AuthenticationToken,并将其发送给已配置的Realm执行必须的认证检查
			// 每个Realm都能在必要时对提交的AuthenticationTokens作出反应
			// 所以这一步在调用login(token)方法时,它会走到MyRealm.doGetAuthenticationInfo()方法中,具体验证方式详见此方法
			logger.info("对用户[" + usernamePasswordToken.getUsername() + "]进行登录验证..验证开始");
			currentUser.login(usernamePasswordToken);
			logger.info("对用户[" + usernamePasswordToken.getUsername() + "]进行登录验证..验证通过");
		} catch (UnknownAccountException uae) {
			logger.error("对用户[" + usernamePasswordToken.getUsername() + "]进行登录验证..验证未通过,未知账户 {}", 
					ExceptionStackTrace.getExceptionInfo(uae));
			loginFailInfo = "未知账户";
		} catch (IncorrectCredentialsException ice) {
			logger.error("对用户[" + usernamePasswordToken.getUsername() + "]进行登录验证..验证未通过,错误的凭证 {}",
					ExceptionStackTrace.getExceptionInfo(ice));
			loginFailInfo = "密码不正确";
		} catch (LockedAccountException lae) {
			logger.error("对用户[" + usernamePasswordToken.getUsername() + "]进行登录验证..验证未通过,账户已锁定 {}",
					ExceptionStackTrace.getExceptionInfo(lae));
			loginFailInfo = "账户已锁定";
		} catch (ExcessiveAttemptsException eae) {
			logger.error("对用户[" + usernamePasswordToken.getUsername() + "]进行登录验证..验证未通过,错误次数过多 {}",
					ExceptionStackTrace.getExceptionInfo(eae));
			loginFailInfo = "错误次数过多";
		} catch (AuthenticationException ae) {
			// 通过处理Shiro的运行时AuthenticationException就可以控制用户登录失败或密码错误时的情景
			logger.error("对用户[" + usernamePasswordToken.getUsername() + "]进行登录验证..验证未通过,堆栈轨迹如下 {}",
					ExceptionStackTrace.getExceptionInfo(ae));
			loginFailInfo = "用户名或密码不正确";
		}
		// 验证是否登录成功
		if (currentUser.isAuthenticated()) {
			SavedRequest savedRequest = WebUtils.getSavedRequest(request);
			String url = null;
			if (!StringUtils.isEmpty(savedRequest) && !StringUtils.isEmpty(savedRequest.getRequestUrl()) && !"/".equals(savedRequest.getRequestUrl()) ) {
				url = savedRequest.getRequestUrl();
				logger.info("==>[1] url:{}", url);
			}else {
				url = request.getContextPath() + "/index.html";
				logger.info("==>[2] url:{}", url);
			}
			logger.info("用户[" + usernamePasswordToken.getUsername() + "]登录认证通过(这里可以进行一些认证通过后的一些系统参数初始化操作)");
			return Response.success().addData("loginUrl", url);
		} else {
			usernamePasswordToken.clear();
			return Response.fail().addData("loginfail", loginFailInfo);
		}
		// 此方法不处理登录成功,由shiro进行处理
	}

	@RequestMapping("/403")
	public String unauthorizedRole() {
		return "403";
	}

	@GetMapping("captcha.jpg")
    public void captcha(HttpServletRequest request, HttpServletResponse response) {
        dreamCaptcha.generate(request, response);
    }
}